home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 3 / Amiga Format CD03 (1996-07-04)(Future Publishing)(GB)(Track 1 of 6)[!][issue 1996-08].iso / comms / netsoftware / nethandler.lha / NetHandler / dnetlib.c < prev    next >
C/C++ Source or Header  |  1989-09-16  |  11KB  |  478 lines

  1. /*
  2.  *  DNETLIB.C
  3.  *
  4.  *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  5.  *
  6.  *  Library Interface for DNET.
  7.  */
  8.  
  9. #define NOEXT
  10. #define NETCOMMON
  11. #include "dnet.h"
  12. #include "netcomm.h"
  13. #include "proto.h"
  14.  
  15. static struct DChannel *MakeChannel U_ARGS((IOR *, char *));
  16. static void DeleteChannel U_ARGS((struct DChannel *));
  17. static void FixSignal     U_ARGS((struct DChannel *));
  18.  
  19. #define NAMELEN sizeof("DNET.PORT.XXXXX")
  20. #define NAMEPAT "DNET.PORT.%ld"
  21.  
  22. PORT *DListen(portnum)
  23. uword portnum;
  24. {
  25.     PORT *port;
  26.     char *ptr;
  27.  
  28.     port = NULL;
  29.     ptr = AllocMem(NAMELEN, MEMF_PUBLIC);   /*  memory the the name     */
  30.     sprintf(ptr, NAMEPAT, portnum);
  31.     Forbid();                               /*  task-atomic operation   */
  32.     if (FindPort(ptr) || !(port = CreatePort(ptr,0)))
  33.        FreeMem(ptr, NAMELEN);
  34.     Permit();
  35.     return(port);
  36. }
  37.  
  38. void
  39. DUnListen(lisport)
  40. PORT *lisport;
  41. {
  42.    register char *ptr;
  43.    ptr = lisport->mp_Node.ln_Name;
  44.  
  45.    if (lisport)
  46.    {
  47.       Forbid();                       /*  task-atomic operation       */
  48.       while (DNAAccept(lisport));     /*  remove all pending requests */
  49.       DeletePort(lisport);            /*  gone!                       */
  50.       Permit();
  51.       FreeMem(ptr, NAMELEN);
  52.    }
  53. }
  54.  
  55. /*
  56.  *  DAccept()
  57.  *
  58.  *  Note:   This call will work even if called by a task which does not
  59.  *          own the listen port.
  60.  */
  61.  
  62. PORT *
  63. DAccept(lisport)
  64. PORT *lisport;
  65. {
  66.     register IOR *ior;
  67.     register struct DChannel * chan;
  68.  
  69. BUG(("DAccept: Entry, port %lx\n", lisport))
  70.  
  71.     chan = NULL;
  72.     while (!chan && (ior = (IOR *)GetMsg(lisport))) {
  73.        switch(ior->io_Command) {
  74.           case DNCMD_SOPEN:
  75.              BUG(("DAccept: SOPEN command\n"))
  76.              chan = MakeChannel(ior, NULL);
  77.              break;
  78.           default:
  79.              BUG(("DAccept: Unrecognized command '%d'\n", ior->io_Command))
  80.              ior->io_Error = 1;
  81.              break;
  82.         }
  83.         BUG(("DAccept: Replying\n"))
  84.         ReplyMsg(&ior->io_Message);
  85.     }
  86.     BUG(("DAccept: After while loop\n"))
  87.     if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
  88.        SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
  89.  
  90.     return(chan ? &chan->port : NULL);
  91. }
  92.  
  93. /*
  94.  *  Refuse a connection
  95.  */
  96.  
  97. DNAAccept(lisport)
  98. PORT *lisport;
  99. {
  100.     IOR *ior;
  101.  
  102.     if (ior = (IOR *)GetMsg(lisport)) {
  103.         ior->io_Error = 1;
  104.         ReplyMsg(&ior->io_Message);
  105.     }
  106.     if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
  107.        SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
  108.     return(ior != NULL);
  109. }
  110.  
  111. void DPri(chan, pri)
  112. struct DChannel * chan;
  113. int pri;
  114. {
  115. }
  116.  
  117.  
  118. PORT *
  119. DOpen(host, portnum, txpri, rxpri)
  120. char *host;
  121. char txpri, rxpri;
  122. uword portnum;
  123. {
  124.     IOR ior;
  125.     struct DChannel *chan;
  126.  
  127.     if (!host)
  128.        host = "0";
  129.     chan = MakeChannel(&ior, host);
  130.     if (rxpri > 126)
  131.         rxpri = 126;
  132.     if (rxpri < -127)
  133.         rxpri = -127;
  134.     if (txpri > 126)
  135.         txpri = 126;
  136.     if (txpri < -127)
  137.         txpri = -127;
  138.     if (chan->dnetport) {
  139.         ior.io_Command = DNCMD_OPEN;
  140.         ior.io_Unit = (void *)portnum;
  141.         ior.io_Offset = (long)chan;
  142.         ior.io_Message.mn_ReplyPort = &chan->port;
  143.         ior.io_Message.mn_Node.ln_Pri = txpri;
  144.         ior.io_Message.mn_Node.ln_Name= (char *)rxpri;
  145.  
  146.         PutMsg(chan->dnetport, &ior.io_Message);
  147.         WaitMsg(&ior);
  148.         if (ior.io_Error == 0) {
  149.            chan->chan = (long)ior.io_Unit;
  150.            FixSignal(chan);
  151.            return(&chan->port);
  152.        }
  153.     }
  154.     DeleteChannel(chan);
  155.     return(NULL);
  156. }
  157.  
  158.  
  159. DNRead(chan, buf, bytes)
  160. struct DChannel * chan;
  161. char *buf;
  162. int bytes;
  163. {
  164.     register IOR *ior;
  165.     int len;
  166.     long n;
  167.  
  168.     len = 0;
  169.     if (chan->eof)
  170.        return(-1);
  171.     while (bytes && ((ior = (IOR *)
  172.                RemHead((struct List *)&chan->rdylist)) || 
  173.                (ior = (IOR *)GetMsg(&chan->port)))) {
  174.        if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) 
  175.        {
  176.           if (!chan->queued)
  177.           {
  178.              BUG(("DNRead: Software Error"));
  179.           }
  180.           else
  181.              --chan->queued;
  182.           if (ior->io_Length)
  183.              FreeMem((char *)ior->io_Data, (long)ior->io_Length);
  184.          FreeMem((char *)ior, (long)sizeof(IOR));
  185.          continue;
  186.        }
  187.       switch(ior->io_Command) 
  188.       {
  189.          case DNCMD_CLOSE:
  190.          case DNCMD_EOF:
  191.             chan->eof = 1;
  192.             ReplyMsg(&ior->io_Message);
  193.             break;
  194.          
  195.          case DNCMD_WRITE:
  196.             n = ior->io_Length - ior->io_Actual;
  197.             if (n <= bytes)
  198.             {
  199.                memcpy(buf, ((char *)ior->io_Data) + ior->io_Actual, n);
  200.                bytes -= n;
  201.                len += n;
  202.                buf += n;
  203.                ReplyMsg(&ior->io_Message);
  204.         } 
  205.         else 
  206.         {
  207.                memcpy(buf, (char *)ior->io_Data + ior->io_Actual, bytes);
  208.                len += bytes;
  209.                ior->io_Actual += bytes;
  210.                bytes = 0;
  211.                Forbid();   /*  DNET device is a task, no need to Disable() */
  212.                ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  213.                AddHead(&chan->port.mp_MsgList, (struct Node *)ior);
  214.                Permit();
  215.             }
  216.         break;
  217.          default:
  218.             ior->io_Error = 1;
  219.             ReplyMsg(&ior->io_Message);
  220.       }
  221.     }
  222.     FixSignal(chan);
  223.     if (chan->eof)
  224.        SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
  225.     return(len);
  226. }
  227.  
  228. int DRead(chan, buf, bytes)
  229. char *buf;
  230. struct DChannel * chan;
  231. int bytes;
  232. {
  233.    long len;
  234.    long n;
  235.  
  236.    len = 0;
  237.    if (chan->eof) 
  238.    {
  239.       BUG(("****DNET EOF!!!\n"));
  240.       return(-1);
  241.    }
  242.  
  243.    while (bytes)
  244.    {
  245.       WaitPort(&chan->port);
  246.       n = DNRead(chan, buf, bytes);
  247.       len += n;
  248.       if (n < 0) break;
  249.       buf += n;
  250.       bytes -= n;
  251.       if (chan->eof) break;
  252.    }
  253.    return(len);
  254. }
  255.  
  256. void DQueue(chan, n)
  257. struct DChannel * chan;
  258. int n;
  259. {
  260.     chan->qlen = n;
  261. }
  262.  
  263. DWrite(chan, buf, bytes)
  264. struct DChannel * chan;
  265. char *buf;
  266. int bytes;
  267. {
  268.     IOR tmpior;
  269.     IOR *ior;
  270.     int error;
  271.  
  272.    error = bytes;
  273.    if (chan->qlen) 
  274.    {
  275.       if (WaitQueue(chan, NULL) >= 0) 
  276.       {
  277.          ior = (IOR *)AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC);
  278.          ior->io_Command = DNCMD_WRITE;
  279.          ior->io_Unit = (void *)chan->chan;
  280.          ior->io_Offset = (long)chan;
  281.          ior->io_Message.mn_ReplyPort = &chan->port;
  282.          ior->io_Data = (APTR)AllocMem(bytes, MEMF_PUBLIC);
  283.          ior->io_Length = bytes;
  284.          memcpy((char *)ior->io_Data, buf, (int)bytes);
  285.          PutMsg(chan->dnetport, &ior->io_Message);
  286.          ++chan->queued;
  287.       } 
  288.       else
  289.       {
  290.          error = -1;
  291.       }
  292.    } 
  293.    else 
  294.    {
  295.       tmpior.io_Command = DNCMD_WRITE;
  296.       tmpior.io_Unit = (void *)chan->chan;
  297.       tmpior.io_Offset = (long)chan;
  298.       tmpior.io_Message.mn_ReplyPort = &chan->port;
  299.       tmpior.io_Data = (APTR)buf;
  300.       tmpior.io_Length = bytes;
  301.       PutMsg(chan->dnetport, &tmpior.io_Message);
  302.       WaitMsg(&tmpior);
  303.       if (tmpior.io_Error)
  304.       {
  305.          error = -1;
  306.          BUG(("*****DWrite: io_Error %d\n", tmpior.io_Error));
  307.          BUGGETC
  308.       }
  309.    }
  310.    FixSignal(chan);
  311.    return(error);
  312. }
  313.  
  314. void DEof(chan)
  315. struct DChannel * chan;
  316. {
  317.     IOR ior;
  318.  
  319.     ior.io_Command = DNCMD_EOF;
  320.     ior.io_Unit = (void *)chan->chan;
  321.     ior.io_Offset = (long)chan;
  322.     ior.io_Message.mn_ReplyPort = &chan->port;
  323.     PutMsg(chan->dnetport, &ior.io_Message);
  324.     WaitMsg(&ior);
  325.     FixSignal(chan);
  326. }
  327.  
  328. void DIoctl(chan, cmd, val, aux)
  329. struct DChannel * chan;
  330. ubyte cmd;
  331. uword val;
  332. ubyte aux;
  333. {
  334.     IOR ior;
  335.  
  336.     ior.io_Command = DNCMD_IOCTL;
  337.     ior.io_Unit = (void *)chan->chan;
  338.     ior.io_Offset = (long)chan;
  339.     ior.io_Message.mn_ReplyPort = &chan->port;
  340.     ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd);
  341.     PutMsg(chan->dnetport, &ior.io_Message);
  342.     WaitMsg(&ior);
  343.     FixSignal(chan);
  344. }
  345.  
  346. int DQuit(host)
  347. char *host;
  348. {
  349.     IOR ior;
  350.     char buf[sizeof(DNETPORTNAME)+32];
  351.     PORT *replyport;
  352.     PORT *dnetport;
  353.  
  354.     if (!host)
  355.     host = "0";
  356.     sprintf(buf, "%s%s", DNETPORTNAME, host);
  357.     if (dnetport = FindPort(buf)) {
  358.         replyport = CreatePort(NULL, 0);
  359.     ior.io_Command = DNCMD_QUIT;
  360.     ior.io_Unit = 0;
  361.     ior.io_Offset = 0;
  362.     ior.io_Message.mn_ReplyPort = replyport;
  363.     PutMsg(dnetport, &ior.io_Message);
  364.     WaitMsg(&ior);
  365.     DeletePort(replyport);
  366.     }
  367.     return(dnetport != NULL);
  368. }
  369.  
  370.  
  371. void DClose(chan)
  372. struct DChannel * chan;
  373. {
  374.     IOR ior;
  375.     IOR *io;
  376.  
  377. BUG(("DClose: Enter\n"))
  378.  
  379.     ior.io_Command = DNCMD_CLOSE;
  380.     ior.io_Unit = (void *)chan->chan;
  381.     ior.io_Offset = (long)chan;
  382.     ior.io_Message.mn_ReplyPort = &chan->port;
  383.     PutMsg(chan->dnetport, &ior.io_Message);
  384.     ++chan->queued;
  385.     chan->qlen = 0;
  386.     WaitQueue(chan, &ior);
  387.     while ((io = (IOR *)RemHead((struct List *)&chan->rdylist)) || 
  388.            (io = (IOR *)GetMsg(&chan->port))) {
  389.     io->io_Error = 1;
  390.     ReplyMsg(&io->io_Message);
  391.     }
  392.     DeleteChannel(chan);
  393. }
  394.  
  395. void WaitMsg(ior)
  396. IOR *ior;
  397. {
  398.     while (ior->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
  399.     Wait(1 << ior->io_Message.mn_ReplyPort->mp_SigBit);
  400.     Forbid();
  401.     Remove((struct Node *)ior);
  402.     Permit();
  403. }
  404.  
  405. int WaitQueue(chan, skipior)
  406. struct DChannel * chan;
  407. IOR *skipior;
  408. {
  409.     register IOR *io;
  410.     short error;
  411.  
  412.    error = 0;
  413.     while (chan->queued > chan->qlen) {     /*  until done  */
  414.     WaitPort(&chan->port);   /*  something   */
  415.     io = (IOR *)GetMsg(&chan->port);
  416.     if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  417.         if (error == 0)
  418.         error = io->io_Error;
  419.         if (io != skipior) {
  420.         if (io->io_Length)
  421.             FreeMem((char *)io->io_Data, io->io_Length);
  422.         FreeMem((char *)io, sizeof(IOR));
  423.         }
  424.         --chan->queued;
  425.     } else {
  426.         AddTail(&chan->rdylist, (struct Node *)io);
  427.     }
  428.     }
  429.     return(error);
  430. }
  431.  
  432. static struct DChannel *MakeChannel(ior, host)
  433. register IOR *ior;
  434. char *host;
  435. {
  436.     struct DChannel * chan;
  437.     char buf[sizeof(DNETPORTNAME)+32];
  438.  
  439. BUG(("MakeChannel: Entry\n"))
  440.  
  441.     chan = (struct DChannel *)AllocMem(sizeof(struct DChannel), 
  442.                                        MEMF_PUBLIC|MEMF_CLEAR);
  443.  
  444.     /*    Name, Pri */
  445.     chan->port.mp_Node.ln_Type = NT_MSGPORT;
  446.     chan->port.mp_SigBit = AllocSignal(-1);
  447.     chan->port.mp_SigTask = FindTask(NULL);
  448.     NewList(&chan->port.mp_MsgList);
  449.     NewList(&chan->rdylist);
  450.     chan->chan = (long)ior->io_Unit;
  451.     ior->io_Offset = (long)chan;
  452.     if (host) {
  453.        sprintf(buf, "%s%s", DNETPORTNAME, host);
  454.     ior->io_Message.mn_ReplyPort = FindPort(buf);
  455.     }
  456.     chan->dnetport = ior->io_Message.mn_ReplyPort;
  457.     return(chan);
  458. }
  459.  
  460. static void
  461. DeleteChannel(chan)
  462. struct DChannel * chan;
  463. {
  464.     FreeSignal(chan->port.mp_SigBit);
  465.     FreeMem((char *)chan, (long)sizeof(struct DChannel));
  466. }
  467.  
  468. static void
  469. FixSignal(chan)
  470. register struct DChannel * chan;
  471. {
  472.     if (chan->port.mp_MsgList.lh_Head != 
  473.              (NODE *)&chan->port.mp_MsgList.lh_Tail ||
  474.        chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail)
  475.     SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
  476. }
  477.  
  478.